[アップデート]Step Functions:動的タイムアウトや組み込み関数などが追加されASLが強化されました
ステートマシンを定義する際に利用するAmazon States Language(以下、ASL)にアップデートがありました。
今回のアップデートで動的タイムアウトや組み込み関数などがサポートされ、ASLがより強化されました。それぞれみていきたいと思います。
アップデート
演算子追加
Choiceステート内で利用できる演算子に以下が加わりました。
- IsNull … パス(以下、変数)の値がNULLかどうかの確認
- IsString … 変数の値が文字列かどうかの確認
- IsNumeric … 変数の値が数値かどうかの確認
- IsBoolean … 変数の値がブール値かどうかの確認
- IsTimestamp … 変数の値がタイムスタンプかどうかの確認
- IsPresent … 変数の存在確認
- StringMatches … 変数の値のパターンが一致するかどうかの確認(ワイルドカード利用可)
- StringEqualsPath … 変数と変数の値が一致するかどうかの確認
例えば、以下のステートではComment
が存在していることかつ、値が文字列の場合は条件を満たし次のステートに遷移します。(Choice ルールに従い状態が遷移します)
"State1": { "Type": "Choice", "Choices": [ { "And": [ { "Variable": "$.Comment", "IsPresent": true }, { "Variable": "$.Comment", "IsString": true } ], "Next": "State2" } ], "Default": "State3" }
IsPresent
を利用することで、存在しない変数にアクセスした際のエラーを防ぐことができます。
Contextオブジェクトへのグローバルアクセス
Context オブジェクトは、ステートマシンの実行名など、ステートマシンの実行に関する情報が含まれています。
アップデート以前はParameters
フィールド内からのみアクセス可能でしたが、こちらの制限がなくなり、以下のようにParameters
フィールド外からもアクセスが可能になりました。
"Check Context Object": { "Type": "Choice", "Choices": [ { "Variable": "$$.Execution.Name", "IsString": true, "Next": "Check Context Object" } ], "Default": "Fail" }
ResultSelectorフィールド追加
Lambda Functionなど、Step Functionsサービスに統合されたAWSサービスを呼び出す際に、結果に加えてメタデータを返すことがあります。 例えば、以下のようにLambda Functionを呼び出すとメタデータも返されます。
ASL定義
"State1":{ "Type":"Task", "Resource":"arn:aws:states:::lambda:invoke", "Parameters":{ "FunctionName":"arn:aws:lambda:ap-northeast-1:xxxxxxxxxx:function:Funtion", }, "ResultSelector": { "RequestId.$": "$.SdkResponseMetadata.RequestId", "StatusCode.$": "$.StatusCode" }, "ResultPath": "$.InvokeResult", "End":true }
メタデータ例
{ "Payload": null, "SdkHttpMetadata": { "AllHttpHeaders": { "x-amzn-Remapped-Content-Length": [ "0" ], "Connection": [ "keep-alive" ], "x-amzn-RequestId": [ "2c17a67a-c238-4fb0-a32f-9524741df09f" ], "Content-Length": [ "0" ], "Date": [ "Fri, 14 Aug 2020 10:48:44 GMT" ], "X-Amzn-Trace-Id": [ "root=1-5f366c0c-e34f89000bc9c900e0b4f400;sampled=0" ] }, "HttpHeaders": { "Connection": "keep-alive", "Content-Length": "0", "Date": "Fri, 14 Aug 2020 10:48:44 GMT", "x-amzn-Remapped-Content-Length": "0", "x-amzn-RequestId": "2c17a67a-c238-4fb0-a32f-9524741df09f", "X-Amzn-Trace-Id": "root=1-5f366c0c-e34f89000bc9c900e0b4f400;sampled=0" }, "HttpStatusCode": 202 }, "SdkResponseMetadata": { "RequestId": "2c17a67a-c238-4fb0-a32f-9524741df09f" }, "StatusCode": 202 }
ResultSelector
を利用することで結果の一部を選択し、それらを出力することが可能です。上記ASL定義の場合、以下のような出力となります。
"InvokeResult": { "RequestId": "2c17a67a-c238-4fb0-a32f-9524741df09f" "StatusCode": 202 }
組み込み関数追加
Taskなしでリテラル値の操作が行える、以下の組み込み関数が追加されました。
- States.Format … フォーマット(文字結合など)
- States.StringToJson … 文字列からJSONに変換
- States.JsonToString … JSONから文字列に変換
- States.Array … 0個以上の引数を取得
以下、JsonToString
の使用例です。
ASL定義
"State1": { "Type": "Pass", "Parameters": { "result.$": "States.JsonToString($.test)" }, "End": true }
入力
{ "test": { "foo": "bar" } }
出力
{ "result": "{\"foo\":\"bar\"}" }
なお、組み込み関数が利用可能なフィールドは制限がありますのでご注意ください。
動的タイムアウト
以前からTimeoutSeconds
でTaskのタイムアウト指定や、Activity利用時のタイムアウト(ハートビート間隔)を指定するHeartbeatSeconds
は存在していましたが、数値を指定する必要があり、動的な値を定義することはできませんでした。
今回のアップデートによりTimeoutSecondsPath
とHeartBeatSecondsPath
がサポートされ、変数で値を指定することが可能になりました。例えば、以下のようにState1
ステートで実行されるLambda Functionでタイムアウトの時間を生成し($.wait_time
に格納)、後続のState2
ステートでタイムアウトを指定することが可能になります。
"State1": { "Type": "Task", "Resource": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxx:function:wait_time_generation", "ResultPath": "$.wait_time", "Next": "State2" }, "State2": { "Type": "Task", "Resource": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxx:function:WaitFuntion", "TimeoutSecondsPath": "$.wait_time", "End": true }
やってみた
上記で紹介したをアップデートをピックアップした、以下のステートマシンを作成してみました。
ASL定義
{ "StartAt":"Check Input", "States":{ "Check Input": { "Type": "Choice", "Choices": [ { "And": [ { "Variable": "$.Comment", "IsPresent": true }, { "Variable": "$.Comment", "StringMatches": "N*n" } ], "Next": "Check Context Object" } ], "Default": "Fail" }, "Check Context Object": { "Type": "Choice", "Choices": [ { "Variable": "$$.Execution.Name", "IsString": true, "Next": "Invoke Event Lambda" } ], "Default": "Fail" }, "Invoke Event Lambda":{ "Type":"Task", "Resource":"arn:aws:states:::lambda:invoke", "Parameters":{ "FunctionName": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:wait_processing", "InvocationType" : "Event" }, "ResultSelector": { "RequestId.$": "$.SdkResponseMetadata.RequestId", "StatusCode.$": "$.StatusCode" }, "ResultPath": "$.InvokeResult", "Next": "Text Format" }, "Text Format": { "Type": "Pass", "Parameters": { "Result.$": "States.Format('Cat: {} Dog : {}', $.Comment, $$.Execution.Name)" }, "Next": "Wait Time Generation" }, "Wait Time Generation": { "Type": "Task", "Resource": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:wait_time_generation", "ResultPath": "$.wait_time", "Next": "IsNumeric Wait Time" }, "IsNumeric Wait Time": { "Type": "Choice", "Choices": [ { "Variable": "$.wait_time", "IsNumeric": true, "Next": "Exec Processing" } ], "Default": "Fail" }, "Exec Processing": { "Type": "Task", "Resource": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:wait_processing", "TimeoutSecondsPath": "$.wait_time", "Next": "Succeed" }, "Succeed": { "Type": "Succeed" }, "Fail": { "Type": "Fail" } } }
ビジュアルワークフロー
ASL定義について説明します。
Check Input
追加された演算子IsPresent
を利用して、Comment
の存在を確認しています。(Comment
は実行時に入力する想定)存在した場合に限りStringMatches
で変数内の値のパターン(ここでは、Nから始まりnで終わる)をチェックします。Choiceタイプのステートのため、チェック結果に応じ処理が分岐されます。
Check Context Object
Contextオブジェクトへのグローバルアクセスの確認ため、Parametersフィールド外からステートマシンの実行名を取得し、IsString
で値が文字列かチェックしています。
Invoke Event Lambda
ここではLambda Functionを非同期で呼び出し、ResultSelector
フィールドでメタデータの一部を取得しています。
Text Format
組み込み関数States.Format
を利用し、実行時に入力する想定のComment
と、Contextオブジェクトから実行名を取得し結合しています。
Wait Time Generation
後続のTaskステートで動的なタイムアウトを設けたいので、Lambda Functionを呼び出しタイムアウト時間を生成しています。
IsNumeric Wait Time
Wait Time Generation
ステートで出力した値をIsNumeric
で数値かどうか確認しています。
Exec Processing
TimeoutSecondsPath
でTaskのタイムアウトを変数でいます。意図的にTaskの実行時間より短いタイムアウトを値を設定しています。
ここでは、このステートでエラー終了すれば想定通りの動作となります。
実行
start-executionで、作成したステートマシンを実行します。
$ SFN_ARN=<作成したステートマシンのARN> $ aws stepfunctions start-execution \ --state-machine-arn ${SFN_ARN} \ --name "pochi" \ --input "{\"Comment\" : \"Nochan\"}" { "executionArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:execution:morimori_update_sfn:pochi", "startDate": "2020-08-15T11:28:18.071000+09:00" }
しばらくすると、想定どおりの結果となりました。
結果についてみていきたいと思います。
Check Input
入力値のComment
で、Nから始まりnで終わるパターンNochan
を指定したので、Check Input
ステートは成功しました。
Check Context Object
実行名pochi
を指定していたので、Check Context Object
も成功です。
Invoke Event Lambda
メタデータの一部が取得できました。
Text Format
値の結合ができました。
Wait Time Generation
Lambda Functionからタイムアウト値を生成しました。
IsNumeric Wait Time
Wait Time Generation
ステートで数値を出力していたのでステートは成功です。
Exec Processing
動的に生成したタイムアウト値(ここでは60秒)で、タイムアウトが発生しステートが失敗しました。
確認は以上です。
今回利用した環境を、AWS SAMテンプレートでアップしておいたので、手元で試してみたい方はご利用ください。
さいごに
今回のアップデートにより、Taskで実施していた処理をASL側に寄せることができ、より簡素なワークフローが作成しやすくなったと思います。まだ日本語のドキュメントは更新されていないようですので、公式ドキュメントを確認する際は、英語のドキュメントを確認ください。